﻿/*
 * RegExpress
 * 
 * Copyright (c) 2010, Daniel McGaughran
 * 
 * Licensed under the Apache Licence, Version 2.0 (the "Licence");
 * you may not use this file except in compliance with the Licence.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the Licence is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the Licence for the specific language governing permissions and
 * limitations under the Licence.
 * 
 */


using System;
using System.Xml;


namespace RegExpressModel.Utility
{
	static class XmlUtility
	{

		/// <summary>
		/// Adds a new attribute to the given target element.
		/// </summary>
		/// <param name="targetElement">The target element to add the new attribute to.</param>
		/// <param name="targetDocument">The target document.</param>
		/// <param name="attrName">Name of the attribute.</param>
		/// <param name="value">The value to set for the attribute.</param>
		internal static void AddAttribute(this XmlElement targetElement, XmlDocument targetDocument,
				string attrName, string value)
		{
			if (targetElement == null || targetDocument == null || String.IsNullOrEmpty(attrName))
				return;

			XmlAttribute attr = targetDocument.CreateAttribute(attrName);
			attr.Value = value;

			targetElement.Attributes.Append(attr);
		}



		/// <summary>
		/// Appends a new empty element to the given target element.
		/// </summary>
		/// <param name="targetElement">The target element to append the created element to.</param>
		/// <param name="targetDocument">The target document.</param>
		/// <param name="elementName">Name of the element to create.</param>
		/// <returns>The created element.</returns>
		internal static XmlElement AppendElement(this XmlElement targetElement, XmlDocument targetDocument,
				string elementName)
		{
			if (targetElement == null || targetDocument == null || String.IsNullOrEmpty(elementName))
				return null;

			XmlElement element = targetDocument.CreateElement(elementName);
			targetElement.AppendChild(element);

			return element;
		}



		/// <summary>
		/// Appends a new element containing a text value to the given target element.
		/// </summary>
		/// <param name="targetElement">The target element to append the text-wrapping element to.</param>
		/// <param name="targetDocument">The target document.</param>
		/// <param name="elementName">Name of the element to create.</param>
		/// <param name="innerValue">The inner text value.</param>
		/// <returns>The created element.</returns>
		internal static XmlElement AppendElement(this XmlElement targetElement, XmlDocument targetDocument,
				string elementName, string innerValue)
		{
			if (targetElement == null || targetDocument == null || String.IsNullOrEmpty(elementName))
				return null;

			XmlElement element = targetDocument.CreateElement(elementName);
			XmlText textNode = targetDocument.CreateTextNode(innerValue);
			element.AppendChild(textNode);
			targetElement.AppendChild(element);

			return element;
		}



		internal static string GetTextAttribute(this XmlNode node, string attributeName)
		{
			XmlAttribute attribute = null;
			try
			{
				attribute = node.Attributes[attributeName];
			}
			catch(Exception)
			{
			}

			if (attribute != null)
				return attribute.Value;

			return "";
		}


		internal static int GetIntAttribute(this XmlNode node, string attributeName)
		{
			XmlAttribute attribute = null;
			try
			{
				attribute = node.Attributes[attributeName];
			}
			catch (Exception)
			{
			}

			if (attribute != null)
			{
				int value;
				if(Int32.TryParse(attribute.Value, out value))
					return value;
			}

			return 0;
		}



		/// <summary>
		/// Gets the text value from the element located by the given XPath.
		/// </summary>
		/// <param name="sourceNode">The source element.</param>
		/// <param name="xPath">The XPath of the parent element.</param>
		/// <returns>The (first) string value if found. If the source element or XPath is invalid, null will
		/// be returned.</returns>
		internal static string GetTextValue(this XmlNode sourceNode, string xPath)
		{
			if (sourceNode == null || String.IsNullOrEmpty(xPath))
				return null;

			XmlNode targetParent = sourceNode.SelectSingleNode(xPath);
			string value = "";

			if (targetParent != null)
			{
				XmlNodeList children = targetParent.ChildNodes;

				foreach(XmlNode childNode in children)
				{
					if (childNode is XmlText || childNode is XmlCDataSection)
					{
						value = childNode.Value;
						break;
					}
				}
			}

			return value;
		}


		/// <summary>
		/// Gets the text value from the element located by the given XPath.
		/// </summary>
		/// <param name="sourceNode">The source node.</param>
		/// <param name="xPath">The XPath of the parent element.</param>
		/// <returns>The (first) string value if found. If the source element or XPath is invalid, null will
		/// be returned.</returns>
		internal static bool GetIntValue(this XmlNode sourceNode, string xPath, ref int outputValue)
		{
			if (sourceNode == null || String.IsNullOrEmpty(xPath))
				return false;

			XmlNode targetParent = sourceNode.SelectSingleNode(xPath);

			if (targetParent != null)
			{
				XmlNodeList children = targetParent.ChildNodes;
				foreach (XmlNode childNode in children)
				{
					if (childNode is XmlText)
					{
						string rawValue = ((XmlText)childNode).Value;
						if (Int32.TryParse(rawValue, out outputValue))
						{
							return true;
						}
					}
				}
			}

			return false;
		}


	}
}
